package com.emaplink.cryptoutil.sm;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileChannelPositionReader {

    /**
     * 使用 FileChannel 读取文件指定位置的内容
     * @param filePath 文件路径
     * @param position 开始读取的位置
     * @param length 要读取的字节数
     * @return 读取到的字节数组
     */
    public static byte[] readWithFileChannel(String filePath, long position, int length)
            throws IOException {

        try (RandomAccessFile file = new RandomAccessFile(filePath, "r");
             FileChannel channel = file.getChannel()) {

            // 检查位置是否有效
            if (position >= channel.size()) {
                return new byte[0];
            }

            // 调整读取长度
            long remaining = channel.size() - position;
            int actualLength = (int) Math.min(length, remaining);

            // 创建缓冲区
            ByteBuffer buffer = ByteBuffer.allocate(actualLength);

            // 读取数据
            channel.position(position);
            channel.read(buffer);

            return buffer.array();
        }
    }

    /**
     * 分段读取大文件指定位置的内容
     * @param filePath 文件路径
     * @param position 开始位置
     * @param length 总长度
     * @param chunkSize 每次读取的块大小
     * @return 读取到的字节数组
     */
    public static byte[] readInChunks(String filePath, long position, int length,
                                      int chunkSize) throws IOException {

        try (RandomAccessFile file = new RandomAccessFile(filePath, "r");
             FileChannel channel = file.getChannel()) {

            if (position >= channel.size()) {
                return new byte[0];
            }

            long remaining = channel.size() - position;
            int actualLength = (int) Math.min(length, remaining);

            ByteBuffer buffer = ByteBuffer.allocate(actualLength);
            channel.position(position);

            // 分段读取
            int totalRead = 0;
            while (totalRead < actualLength) {
                int bytesToRead = Math.min(chunkSize, actualLength - totalRead);
                ByteBuffer chunkBuffer = ByteBuffer.allocate(bytesToRead);

                int bytesRead = channel.read(chunkBuffer);
                if (bytesRead == -1) {
                    break; // 文件结束
                }

                // 将块数据复制到主缓冲区
                chunkBuffer.flip();
                buffer.put(chunkBuffer);
                totalRead += bytesRead;
            }

            return buffer.array();
        }
    }
}
